//+--------------------------------------------------------------------------------
//| Copyright (c) 2012 - 2013 ### an.vuongngocduy
//| This file is a part of Compact Game Engine (CGE)
//+--------------------------------------------------------------------------------
#include "cgeImageTranscoderBMP.h"

namespace cge
{
	namespace gfx
	{
		//=========================================================================================
		s8 ImageTranscoderBMP::LoadImage(Stream& inStream, Image& image) const
		{
			Allocator<u8> localAlloc;
			FileHeaderBMP fileHeader;
			CoreHeaderBMP coreHeader;

			inStream.Read((u8*)&fileHeader, sizeof(FileHeaderBMP));
			inStream.Read((u8*)&coreHeader, sizeof(CoreHeaderBMP));

			if(fileHeader.Magick != /*BM*/0x4D42) // not Bitmap file 
				return -1;

			image.Dispose();
			Image::Descriptor* desc = this->lockOn(image);
			desc->Dimension.Set(coreHeader.Width, coreHeader.Height);
			
			switch(coreHeader.BitsPerPixel)
			{
			case 24:
				desc->Format = PixelFormat::Bpp24_B8G8R8;
				break;

			default:
				desc->Format = PixelFormat::Bpp32_A8R8G8B8;
				break;
			}

			desc->Data = localAlloc.Allocate(image.Size());
			
			if(desc->Data == null) //out of memory
				return 1;

			u8* bmpData = localAlloc.Allocate(coreHeader.ImageSize);
			
			if(bmpData == null) // out of memory
				return 1;

			inStream.Seek(fileHeader.DataOffset, true);

			inStream.Read(bmpData, coreHeader.ImageSize);

			u32 bmpRowSize = coreHeader.ImageSize / coreHeader.Height;
			u32 imgRowSize = (image.BitsPerPixel() / 8) * coreHeader.Width;

			for(u32 row = 0; row < coreHeader.Height; row++)
			{
				// pixels are stored from bottom to top and in BGR format
				u8* pData = desc->Data + (row * imgRowSize);
				memcpy(pData, bmpData + bmpRowSize * (coreHeader.Height - (row + 1)),imgRowSize);
				
			#if 0 // turn on if store image as R8G8B8
				if(coreHeader.BitsPerPixel == 24)
				{
					// swap B and R
					for(u32 col = 0; col < imgRowSize; col += 3)
					{
						pData[col] = pData[col] ^ pData[col + 2];
						pData[col + 2] = pData[col] ^ pData[col + 2];
						pData[col] = pData[col] ^ pData[col + 2];
					}
				}
			#endif
			}

			localAlloc.Deallocate(bmpData);
			
			bmpData = null;
			
			return 0;
		}

		//=========================================================================================
		s8 ImageTranscoderBMP::SaveImage(Stream& outStream, const Image& image) const
		{
			Allocator<u8> localAlloc;
			CoreHeaderBMP coreHeader;
			coreHeader.BitsPerPixel = image.BitsPerPixel();
			coreHeader.Width = image.Width();
			coreHeader.Height = image.Height();
			u32 bmpRowSize = static_cast<u32>(( image.BitsPerPixel() * image.Width() + 31 ) / 32) * 4;
			coreHeader.ImageSize = bmpRowSize *  coreHeader.Height;
			u8* rowData = localAlloc.Allocate(bmpRowSize);
			return 0;
		}

		//=========================================================================================
	}
}